﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Collections;

namespace yncTech.Common
{
    /// <summary>
    /// Reflector class.
    /// </summary>
    public class Reflector
    {
        #region FindAttribute

        /// <summary>
        /// Get enum item's specify attribute value.
        /// </summary>
        /// <param name="instance">Enum items</param>
        /// <param name="attributeType">Attribute type you want to get.</param>
        /// <returns>Attribute value.</returns>
        public static Attribute FindAttribute(Enum instance, Type attributeType)
        {
            Type type = instance.GetType();
            MemberInfo[] memberInfos = type.GetMember(instance.ToString());
            if (memberInfos != null && memberInfos.Length > 0)
            {
                MemberInfo memberInfo = memberInfos[0] as MemberInfo;
                IList attributes = FindAttributes(false, memberInfo, attributeType);
                if (attributes != null && attributes.Count > 0)
                {
                    return attributes[0] as Attribute;
                }
            }
            return null;
        }

        #endregion

        #region FindAttributes

        /// <summary>
        /// Get enum item's attribute value in attribute list.
        /// </summary>
        /// <param name="allowDuplicates">Allow duplicates.</param>
        /// <param name="memberInfo">MemberInfo</param>
        /// <param name="attributeTypes">Attribute list</param>
        /// <returns>Attribute value list</returns>
        public static IList FindAttributes(bool allowDuplicates, MemberInfo memberInfo, params Type[] attributeTypes)
        {
            IList result = new ArrayList();
            foreach (Type attributeType in attributeTypes)
            {
                object[] attributes = memberInfo.GetCustomAttributes(attributeType, true);
                int max = allowDuplicates ? attributes.Length : 1;
                if (attributes != null && attributes.Length > 0)
                {
                    for (int i = 0; i < max; i++)
                    {
                        result.Add(attributes[i]);
                    }
                }
            }
            return result;
        }

        #endregion

        #region FindPropertys

        /// <summary>
        /// Find propertys on specited type
        /// </summary>
        /// <param name="type">Type</param>
        /// <returns>PropertyInfo array</returns>
        public static PropertyInfo[] FindPropertys(Type type)
        {
            return type.GetProperties();
        }

        #endregion

        #region FindType

        /// <summary>
        /// Create object from appointed assembly by name.
        /// </summary>
        /// <param name="assembly">Assembly instance.</param>
        /// <param name="typeName">The name of the type you want to create.</param>
        /// <returns>Type created</returns>		
        public static Type FindType(Assembly assembly, string typeName)
        {
            Type type = assembly.GetType(typeName);
            if (type == null)
            {
                throw new Exception(string.Format("组件{0}中不存在类型{1}", assembly.FullName, typeName));
            }
            return type;
        }

        /// <summary>
        /// Find type in specited assembly
        /// </summary>
        /// <param name="assemblyName">Assembly name</param>
        /// <param name="typeName">Type name</param>
        /// <returns>Type</returns>
        public static Type FindType(string assemblyName, string typeName)
        {
            Assembly assembly = FindAssembly(assemblyName);
            return FindType(assembly, typeName);
        }

        #endregion

        #region GetPropertyValue

        /// <summary>
        /// Get property value
        /// </summary>
        /// <param name="instance">Instance</param>
        /// <param name="propertyName">Property name</param>
        /// <returns>value</returns>
        public static object GetPropertyValue(object instance, string propertyName)
        {
            PropertyInfo propertyInfo = instance.GetType().GetProperty(propertyName);
            if (propertyInfo == null)
            {
                throw new Exception(string.Format("对象{0}中不存在属性{1}", instance.GetType().FullName, propertyName));
            }
            return propertyInfo.GetValue(instance, null);
        }

        #endregion

        #region SetPropertyValue

        /// <summary>
        /// Set property value
        /// </summary>
        /// <param name="instance">Instance</param>
        /// <param name="propertyName">Property name</param>
        /// <param name="value">value</param>
        public static void SetPropertyValue(object instance, string propertyName, object value)
        {
            PropertyInfo propertyInfo = instance.GetType().GetProperty(propertyName);
            if (propertyInfo == null)
            {
                throw new Exception(string.Format("对象{0}中不存在属性{1}", instance.GetType().FullName, propertyName));
            }
            propertyInfo.SetValue(instance, value, null);
        }

        #endregion

        #region FindAssembly

        /// <summary>
        /// Get assembly by assembly name
        /// </summary>
        /// <param name="assemblyName">Assembly name</param>
        /// <returns>Assembly instance.</returns>
        public static Assembly FindAssembly(string assemblyName)
        {
            try
            {
                return Assembly.Load(assemblyName);
            }
            catch (ArgumentNullException)
            {
                throw new Exception(string.Format("程序集名称不能为空"));
            }
            catch (ArgumentException)
            {
                throw new Exception(string.Format("程序集名称不能为空"));
            }
            catch (FileNotFoundException)
            {
                throw new Exception(string.Format("程序集{0}不存在", assemblyName));
            }
            catch (BadImageFormatException)
            {
                throw new Exception(string.Format("{0}不是有效程序集", assemblyName));
            }
        }

        #endregion
    }
}
